home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 November / november_2001.iso / Browsers / Netscape 6.1 / browser.xpi / bin / chrome / comm.jar / content / editor / EdConvertToTable.js < prev    next >
Encoding:
JavaScript  |  2001-05-18  |  9.4 KB  |  332 lines

  1. /* 
  2.  * The contents of this file are subject to the Netscape Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/NPL/
  6.  *  
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  *  
  12.  * The Original Code is Mozilla Communicator client code, released
  13.  * March 31, 1998.
  14.  * 
  15.  * The Initial Developer of the Original Code is Netscape
  16.  * Communications Corporation. Portions created by Netscape are
  17.  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
  18.  * Rights Reserved.
  19.  * 
  20.  * Contributor(s): 
  21.  */
  22.  
  23. var dialog;
  24. var gIndex;
  25. var gCommaIndex = "0";
  26. var gSpaceIndex = "1";
  27. var gOtherIndex = "2";
  28.  
  29. // dialog initialization code
  30. function Startup()
  31. {
  32.   if (!InitEditorShell())
  33.     return;
  34.  
  35.   doSetOKCancel(onOK, onCancel);
  36.  
  37.   // Create dialog object to store controls for easy access
  38.   dialog = new Object;
  39.   dialog.sepRadioGroup      = document.getElementById("SepRadioGroup");
  40.   dialog.sepCharacterInput  = document.getElementById("SepCharacterInput");
  41.   dialog.deleteSepCharacter = document.getElementById("DeleteSepCharacter");
  42.   
  43.   // We persist the user's separator character
  44.   dialog.sepCharacterInput.value = dialog.sepRadioGroup.getAttribute("character");
  45.  
  46.   // Always default to deleting the separator character
  47.   dialog.deleteSepCharacter.checked = true;
  48.  
  49.   gIndex = dialog.sepRadioGroup.getAttribute("index");
  50.  
  51.   switch (gIndex)
  52.   {
  53.     case gCommaIndex:
  54.     default:
  55.       document.getElementById("comma").checked = true;
  56.       break;
  57.     case gSpaceIndex:
  58.       document.getElementById("space").checked = true;
  59.       break;
  60.     case gOtherIndex:
  61.       document.getElementById("other").checked = true;
  62.       break;
  63.   }
  64.  
  65.   // Set initial enable state on character input
  66.   SelectCharacter(gIndex);
  67.  
  68.   SetTextboxFocus(dialog.sepRadioGroup);
  69.  
  70.   SetWindowLocation();
  71. }
  72.  
  73. function InputSepCharacter()
  74. {
  75.   var str = dialog.sepCharacterInput.value;
  76.  
  77.   // Limit input to 1 character
  78.   if (str.length > 1)
  79.     str.slice(0,1);
  80.  
  81.   // We can never allow tag delimeters for separator character
  82.   if (str == "<" || str == ">")
  83.     str = "";
  84.  
  85.   dialog.sepCharacterInput.value = str;
  86. }
  87.  
  88. function SelectCharacter(radioGroupIndex)
  89. {
  90.   gIndex = radioGroupIndex;
  91.   SetElementEnabledById("SepCharacterInput", gIndex == gOtherIndex);
  92. }
  93.  
  94. function onOK()
  95. {
  96.   var sepCharacter = "";
  97.   switch ( gIndex )
  98.   {
  99.     case gCommaIndex:
  100.       sepCharacter = ",";
  101.       break;
  102.     case gSpaceIndex:
  103.       sepCharacter = " ";
  104.       break;
  105.     case gOtherIndex:
  106.       sepCharacter = dialog.sepCharacterInput.value.slice(0,1);
  107.       break;
  108.   }
  109.  
  110.   // 1 = OutputSelectionOnly, 1024 = OutputLFLineBreak
  111.   // 256 = OutputEncodeEntities
  112.   var str = editorShell.GetContentsAs("text/html", 1+1024);
  113.  
  114.   // Replace nbsp with spaces:
  115.   str = str.replace(/\u00a0/g, " ");
  116.  
  117.   // Strip out </p> completely
  118.   str = str.replace(/\s*<\/p>\s*/g, "");
  119.  
  120.   // Trim whitespace adjacent to <p> and <br> tags
  121.   //  and replace <p> with <br> 
  122.   //  (which will be replaced with </tr> below)
  123.   str = str.replace(/\s*<p>\s*|\s*<br>\s*/g, "<br>");
  124.  
  125.   // Trim leading <br>s
  126.   str = str.replace(/^(<br>)+/, "");
  127.  
  128.   // Trim trailing <br>s
  129.   str = str.replace(/(<br>)+$/, "");
  130.  
  131.   // Reduce multiple internal <br> to just 1
  132.   str = str.replace(/(<br>)+/g, "<br>");
  133.  
  134.   // Trim leading and trailing spaces
  135.   str = str.replace(/^\s+|\s+$/, "");
  136.  
  137.   // Remove all tag contents so we don't replace
  138.   //   separator character within tags
  139.   // Also converts lists to something usefull
  140.   var stack = [];
  141.   var start;
  142.   var end;
  143.   var searchStart = 0;
  144.   var listSeparator = "";
  145.   var listItemSeparator = "";
  146.   var endList = false;
  147.  
  148.   do {
  149.     start = str.indexOf("<", searchStart);
  150.  
  151.     if (start >= 0)
  152.     {
  153.       var end = str.indexOf(">", start+1);
  154.       if (end > start)
  155.       {
  156.         var tagContent = TrimString(str.slice(start+1, end));
  157.  
  158.         if ( tagContent.match(/^ol|^ul|^dl/) )
  159.         {
  160.           //  Replace list tag with <BR> to start new row 
  161.           //   at begining of second or greater list tag
  162.           str = str.slice(0, start) + listSeparator + str.slice(end+1);
  163.           if (listSeparator == "")
  164.             listSeparator = "<br>";
  165.           
  166.           // Reset for list item separation into cells
  167.           listItemSeparator = "";
  168.         }
  169.         else if ( tagContent.match(/^li|^dt|^dd/) )
  170.         {
  171.           // Start a new row if this is first item after the ending the last list
  172.           if (endList)
  173.             listItemSeparator = "<br>";
  174.  
  175.           // Start new cell at begining of second or greater list items
  176.           str = str.slice(0, start) + listItemSeparator + str.slice(end+1);
  177.  
  178.           if (endList || listItemSeparator == "")
  179.             listItemSeparator = sepCharacter;
  180.  
  181.           endList = false;
  182.         }
  183.         else 
  184.         {
  185.           // Find end tags
  186.           endList = tagContent.match(/^\/ol|^\/ul|^\/dl/);
  187.           if ( endList || tagContent.match(/^\/li|^\/dt|^\/dd/) )
  188.           {
  189.             // Strip out tag
  190.             str = str.slice(0, start) + str.slice(end+1);
  191.           }
  192.           else
  193.           {
  194.             // Not a list-related tag: Store tag contents in an array
  195.             stack.push(tagContent);
  196.            
  197.             // Keep the "<" and ">" while removing from source string
  198.             start++;
  199.             str = str.slice(0, start) + str.slice(end);
  200.           }
  201.         }
  202.       }
  203.       searchStart = start + 1;
  204.     }
  205.   } while (start >= 0);
  206.  
  207.   // Replace separator characters with table cells
  208.   var replaceString;
  209.   if (dialog.deleteSepCharacter.checked)
  210.   {
  211.     replaceString = "";
  212.     // Replace one or more adjacent spaces
  213.     if (sepCharacter == " ")
  214.       sepCharacter += "\+"; 
  215.   }  
  216.   else
  217.   {
  218.     // Don't delete separator character,
  219.     //  so include it at start of string to replace
  220.     replaceString = sepCharacter;
  221.   }
  222.   replaceString += "<td>"; 
  223.  
  224.   if (sepCharacter.length > 0)
  225.   {
  226.     var pattern = new RegExp("\\" + sepCharacter, "g");
  227.     str = str.replace(pattern, replaceString);
  228.   }
  229.  
  230.   // Put back tag contents that we removed above
  231.   searchStart = 0;
  232.   var stackIndex = 0;
  233.   do {
  234.     start = str.indexOf("<", searchStart);
  235.     end = start + 1;
  236.     if (start >= 0 && str.charAt(end) == ">")
  237.     {
  238.       // We really need a FIFO stack!
  239.       str = str.slice(0, end) + stack[stackIndex++] + str.slice(end);
  240.     }
  241.     searchStart = end;
  242.  
  243.   } while (start >= 0);
  244.  
  245.   // End table row and start another for each br or p
  246.   str = str.replace(/\s*<br>\s*/g, "</tr>\n<tr><td>");
  247.  
  248.   // Add the table tags and the opening and closing tr/td tags
  249.   // Default table attributes should be same as those used in nsHTMLEditor::CreateElementWithDefaults()
  250.   // (Default width="100%" is used in EdInsertTable.js)
  251.   str = "<table border=\"1\" width=\"100%\" cellpadding=\"2\" cellspacing=\"2\">\n<tr><td>" + str + "</tr>\n</table>\n";
  252.  
  253.   editorShell.BeginBatchChanges();
  254.   
  255.   // Delete the selection -- makes it easier to find where table will insert
  256.   editorShell.DeleteSelection(0);
  257.  
  258.   var anchorNodeBeforeInsert = editorShell.editorSelection.anchorNode;
  259.   var offset = editorShell.editorSelection.anchorOffset;
  260.   var nodeBeforeTable = null;
  261.   var nodeAfterTable = null;
  262.   if (anchorNodeBeforeInsert.nodeType == Node.TEXT_NODE)
  263.   {
  264.     // Text was split. Table should be right after the first or before 
  265.     nodeBeforeTable = anchorNodeBeforeInsert.previousSibling;
  266.     nodeAfterTable = anchorNodeBeforeInsert;
  267.   }
  268.   else
  269.   {
  270.     // Table should be inserted right after node pointed to by selection
  271.     if (offset > 0)
  272.       nodeBeforeTable = anchorNodeBeforeInsert.childNodes.item(offset - 1);
  273.  
  274.     nodeAfterTable = anchorNodeBeforeInsert.childNodes.item(offset);
  275.   }
  276.   
  277.   editorShell.InsertSource(str);
  278.  
  279.   var table = null;
  280.   if (nodeAfterTable)
  281.   {
  282.     var previous = nodeAfterTable.previousSibling;
  283.     if (previous && previous.nodeName.toLowerCase() == "table")
  284.       table = previous;
  285.   }
  286.   if (!table && nodeBeforeTable)
  287.   {
  288.     var next = nodeBeforeTable.nextSibling;
  289.     if (next && next.nodeName.toLowerCase() == "table")
  290.       table = next;
  291.   }
  292.  
  293.   if (table)
  294.   {
  295.     // Fixup table only if pref is set
  296.     var prefs = GetPrefs();
  297.     try {
  298.       if (prefs && prefs.GetBoolPref("editor.table.maintain_structure") )
  299.         editorShell.NormalizeTable(table);
  300.     } catch(ex) {
  301.       dump(ex);
  302.     }
  303.  
  304.     // Put caret in first cell
  305.     var firstRow = editorShell.GetFirstRow(table);
  306.     if (firstRow)
  307.     {
  308.       var node2 = firstRow.firstChild;
  309.       do {
  310.         if (node2.nodeName.toLowerCase() == "td" ||
  311.             node2.nodeName.toLowerCase() == "th")
  312.         {
  313.           cellNode = node2;
  314.           editorShell.editorSelection.collapse(node2, 0);
  315.           break;
  316.         }
  317.         node2 = node.nextSibling;
  318.       } while (node2);
  319.     }
  320.   }
  321.  
  322.   editorShell.EndBatchChanges();
  323.  
  324.   // Save persisted attributes
  325.   dialog.sepRadioGroup.setAttribute("index", gIndex);
  326.   if (gIndex == gOtherIndex)
  327.     dialog.sepRadioGroup.setAttribute("character", sepCharacter);
  328.  
  329.   SaveWindowLocation();
  330.   return true;
  331. }
  332.